/*
 * CC3ActionInterval.m
 *
 * cocos3d 0.6.1
 * Author: Bill Hollings
 * Copyright (c) 2010-2011 The Brenwill Workshop Ltd. All rights reserved.
 * http://www.brenwill.com
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 * http://en.wikipedia.org/wiki/MIT_License
 * 
 * See header file CC3ActionInterval.h for full API documentation.
 */

#include "CC3ActionInterval.h"
#include "CC3TargettingNode.h"


#pragma mark -
#pragma mark CC3TransformBy

CC3TransformBy::CC3TransformBy()
{
}

CC3TransformBy::~CC3TransformBy()
{
}

bool CC3TransformBy::initWithDuration(cocos2d::ccTime t, CC3Vector aVector)
{
	if( CCActionInterval::initWithDuration(t) ) 
	{
		diffVector = aVector;
		return true;
	}
	
	return false;
}

CC3TransformBy* CC3TransformBy::actionWithDuration(cocos2d::ccTime t, CC3Vector aVector)
{
	CC3TransformBy* pAction = new CC3TransformBy;
	if (pAction) 
	{
		pAction->autorelease();
		pAction->initWithDuration(t, aVector);
	}
	
	return pAction;
}

CC3TransformBy* CC3TransformBy::reverse()
{
	return CC3TransformBy::actionWithDuration(getDuration(), CC3VectorNegate(diffVector));
}

void CC3TransformBy::startWithTarget(cocos2d::CCNode* aTarget)
{
	CCActionInterval::startWithTarget(aTarget);
	startVector = getTargetVector();
}

CC3Vector CC3TransformBy::getTargetVector()
{
	return kCC3VectorZero;
}

void CC3TransformBy::setTargetVector(CC3Vector aVector)
{
}

void CC3TransformBy::update(cocos2d::ccTime t)
{
	setTargetVector(CC3VectorAdd(startVector, CC3VectorScaleUniform(diffVector, t)));
}

//@interface CC3TransformBy (TemplateMethods)
//@property(nonatomic, assign) CC3Vector targetVector;
//@end
//
//@implementation CC3TransformBy
//
//-(id) initWithDuration: (ccTime) t differenceVector: (CC3Vector) aVector {
//	if( (self = [super initWithDuration: t]) ) {
//		diffVector = aVector;
//	}
//	return self;
//}
//
//+(id) actionWithDuration: (ccTime) t differenceVector: (CC3Vector) aVector {
//	return [[[self alloc] initWithDuration: t differenceVector: aVector] autorelease];
//}
//
//-(id) copyWithZone: (NSZone*) zone {
//	return [[[self class] allocWithZone: zone] initWithDuration: [self duration] differenceVector: diffVector];
//}
//
//-(id) reverse {
//	return [[self class] actionWithDuration: self.duration differenceVector: CC3VectorNegate(diffVector)];
//}
//
//-(void) startWithTarget:(CC3Node*) aTarget {
//	[super startWithTarget: aTarget];
//	startVector = self.targetVector;
//}
//
//-(void) update: (ccTime) t {	
//	self.targetVector = CC3VectorAdd(startVector, CC3VectorScaleUniform(diffVector, t));
//}
//
//-(CC3Vector) targetVector {
//	return kCC3VectorZero;
//}
//
//-(void) setTargetVector: (CC3Vector) aVector {}
//
//-(NSString*) description {
//	return [NSString stringWithFormat: @"%@ start: %@, diff: %@", [self class],
//			NSStringFromCC3Vector(startVector), NSStringFromCC3Vector(diffVector)];
//}
//
//@end


#pragma mark -
#pragma mark CC3MoveBy

CC3MoveBy::CC3MoveBy()
{
}

CC3MoveBy::~CC3MoveBy()
{
}

bool CC3MoveBy::initWithDuration(cocos2d::ccTime t, CC3Vector aTranslation)
{
	return CC3TransformBy::initWithDuration(t, aTranslation);
}

CC3MoveBy* CC3MoveBy::actionWithDuration(cocos2d::ccTime t, CC3Vector aVector)
{
	CC3MoveBy* pAction = new CC3MoveBy;
	if (pAction) 
	{
		pAction->autorelease();
		pAction->initWithDuration(t, aVector);
	}
	
	return pAction;
}

CC3Vector CC3MoveBy::getTargetVector()
{
	return ((CC3Node*)getTarget())->getLocation();
}

void CC3MoveBy::setTargetVector(CC3Vector aVector)
{
	((CC3Node*)getTarget())->setLocation(aVector);
}

//@implementation CC3MoveBy
//
//-(id) initWithDuration: (ccTime) t moveBy: (CC3Vector) aTranslation {
//	return [self initWithDuration: t differenceVector: aTranslation];
//}
//
//+(id) actionWithDuration: (ccTime) t moveBy: (CC3Vector) aTranslation {
//	return [self actionWithDuration: t differenceVector: aTranslation];
//}
//
//-(CC3Vector) targetVector {
//	return ((CC3Node*)self.target).location;
//}
//
//-(void) setTargetVector: (CC3Vector) aLocation {
//	((CC3Node*)self.target).location = aLocation;
//}
//
//@end


#pragma mark -
#pragma mark CC3RotateBy

CC3RotateBy::CC3RotateBy()
{
}

CC3RotateBy::~CC3RotateBy()
{
}

bool CC3RotateBy::initWithDuration(cocos2d::ccTime t, CC3Vector aRotation)
{
	return CC3TransformBy::initWithDuration(t, aRotation);
}

CC3RotateBy* CC3RotateBy::actionWithDuration(cocos2d::ccTime t, CC3Vector aVector)
{
	CC3RotateBy* pAction = new CC3RotateBy;
	if (pAction) 
	{
		pAction->autorelease();
		pAction->initWithDuration(t, aVector);
	}
	
	return pAction;
}

CC3Vector CC3RotateBy::getTargetVector()
{
	return ((CC3Node*)getTarget())->getRotation();
}

void CC3RotateBy::setTargetVector(CC3Vector aVector)
{
	((CC3Node*)getTarget())->setRotation(aVector);
}

//@implementation CC3RotateBy
//
//-(id) initWithDuration: (ccTime) t rotateBy: (CC3Vector) aRotation {
//	return [self initWithDuration: t differenceVector: aRotation];
//}
//
//+(id) actionWithDuration: (ccTime) t rotateBy: (CC3Vector) aRotation {
//	return [self actionWithDuration: t differenceVector: aRotation];
//}
//
//-(CC3Vector) targetVector {
//	return ((CC3Node*)self.target).rotation;
//}
//
//-(void) setTargetVector: (CC3Vector) aRotation {
//	((CC3Node*)self.target).rotation = aRotation;
//}
//
//@end


#pragma mark -
#pragma mark CC3RotateByAngle

CC3RotateByAngle::CC3RotateByAngle()
{
}

CC3RotateByAngle::~CC3RotateByAngle()
{
}

bool CC3RotateByAngle::initWithDuration(cocos2d::ccTime t, GLfloat anAngle)
{
	if( cocos2d::CCActionInterval::initWithDuration(t) ) 
	{
		diffAngle = anAngle;
		return true;
	}
	
	return false;
}

CC3RotateByAngle* CC3RotateByAngle::actionWithDuration(cocos2d::ccTime t, GLfloat anAngle)
{
	CC3RotateByAngle* pAction = new CC3RotateByAngle;
	if (pAction) 
	{
		pAction->autorelease();
		pAction->initWithDuration(t, anAngle);
	}
	
	return pAction;
}

CC3RotateByAngle* CC3RotateByAngle::reverse()
{
	return CC3RotateByAngle::actionWithDuration(getDuration(), -diffAngle);
}

void CC3RotateByAngle::startWithTarget(cocos2d::CCNode* aTarget)
{
	cocos2d::CCActionInterval::startWithTarget(aTarget);
	CC3Node* pNode = (CC3Node*)aTarget;
	startAngle = pNode->getRotationAngle();
}

void CC3RotateByAngle::update(cocos2d::ccTime t)
{
	((CC3Node*)getTarget())->setRotationAngle(startAngle + (diffAngle * t));
}

//@implementation CC3RotateByAngle
//
//-(id) initWithDuration: (ccTime) t rotateByAngle: (GLfloat) anAngle {
//	if( (self = [super initWithDuration: t]) ) {
//		diffAngle = anAngle;
//	}
//	return self;
//}
//
//+(id) actionWithDuration: (ccTime) t rotateByAngle: (GLfloat) anAngle {
//	return [[[self alloc] initWithDuration: t rotateByAngle: anAngle] autorelease];
//}
//
//-(id) copyWithZone: (NSZone*) zone {
//	return [[[self class] allocWithZone: zone] initWithDuration: [self duration]
//												  rotateByAngle: diffAngle];
//}
//
//-(id) reverse {
//	return [[self class] actionWithDuration: self.duration rotateByAngle: -diffAngle];
//}
//
//-(void) startWithTarget:(CC3Node*) aTarget {
//	[super startWithTarget: aTarget];
//	startAngle = aTarget.rotationAngle;
//}
//
//-(void) update: (ccTime) t {	
//	((CC3Node*)self.target).rotationAngle = startAngle + (diffAngle * t);
//}
//
//-(NSString*) description {
//	return [NSString stringWithFormat: @"%@ start: %.3f, end: %.3f, diff: %.3f",
//			[self class], startAngle, startAngle + diffAngle, diffAngle];
//}
//
//@end


#pragma mark -
#pragma mark CC3ScaleBy

CC3ScaleBy::CC3ScaleBy()
{
}

CC3ScaleBy::~CC3ScaleBy()
{
}

bool CC3ScaleBy::initWithDuration(cocos2d::ccTime t, CC3Vector aScale)
{
	return CC3TransformBy::initWithDuration(t, aScale);
}

CC3ScaleBy* CC3ScaleBy::actionWithDuration(cocos2d::ccTime t, CC3Vector aScale)
{
	CC3ScaleBy* pAction = new CC3ScaleBy;
	if (pAction) 
	{
		pAction->autorelease();
		pAction->initWithDuration(t, aScale);
	}
	
	return pAction;
}

CC3Vector CC3ScaleBy::getTargetVector()
{
	return ((CC3Node*)getTarget())->getScale();
}

void CC3ScaleBy::setTargetVector(CC3Vector aVector)
{
	((CC3Node*)getTarget())->setScale(aVector);
}

//@implementation CC3ScaleBy
//
//-(id) initWithDuration: (ccTime) t scaleBy: (CC3Vector) aScale {
//	return [self initWithDuration: t differenceVector: aScale];
//}
//
//+(id) actionWithDuration: (ccTime) t scaleBy: (CC3Vector) aScale {
//	return [self actionWithDuration: t differenceVector: aScale];
//}
//
//-(CC3Vector) targetVector {
//	return ((CC3Node*)self.target).scale;
//}
//
//-(void) setTargetVector: (CC3Vector) aScale {
//	((CC3Node*)self.target).scale = aScale;
//}
//
//@end


#pragma mark CC3TransformTo

CC3TransformTo::CC3TransformTo()
{
}

CC3TransformTo::~CC3TransformTo()
{
}

bool CC3TransformTo::initWithDuration(cocos2d::ccTime t, CC3Vector aVector)
{
	if( cocos2d::CCActionInterval::initWithDuration(t) ) 
	{
		endVector = aVector;
		return true;
	}
	
	return false;
}

CC3TransformTo* CC3TransformTo::actionWithDuration(cocos2d::ccTime t, CC3Vector aVector)
{
	CC3TransformTo* pAction = new CC3TransformTo;
	if (pAction) 
	{
		pAction->autorelease();
		pAction->initWithDuration(t, aVector);
	}
	
	return pAction;
}

CC3TransformTo* CC3TransformTo::reverse()
{
	return CC3TransformTo::actionWithDuration(getDuration(), startVector);
}

void CC3TransformTo::startWithTarget(cocos2d::CCNode* aTarget)
{
	CC3TransformBy::startWithTarget(aTarget);
	diffVector = CC3VectorDifference(endVector, startVector);
}

//@implementation CC3TransformTo
//
//-(id) initWithDuration: (ccTime) t endVector: (CC3Vector) aVector {
//	if( (self = [super initWithDuration: t]) ) {
//		endVector = aVector;
//	}
//	return self;
//}
//
//+(id) actionWithDuration: (ccTime) t endVector: (CC3Vector) aVector {
//	return [[[self alloc] initWithDuration: t endVector: aVector] autorelease];
//}
//
//-(id) copyWithZone: (NSZone*) zone {
//	return [[[self class] allocWithZone: zone] initWithDuration: [self duration]
//													  endVector: endVector];
//}
//
//-(id) reverse {
//	return [[self class] actionWithDuration: self.duration endVector: startVector];
//}
//
//-(void) startWithTarget:(CC3Node*) aTarget {
//	[super startWithTarget: aTarget];
//	diffVector = CC3VectorDifference(endVector, startVector);
//}
//
//-(NSString*) description {
//	return [NSString stringWithFormat: @"%@ start: %@, end: %@, diff: %@", [self class],
//			NSStringFromCC3Vector(startVector), NSStringFromCC3Vector(endVector),
//			NSStringFromCC3Vector(diffVector)];
//}
//
//@end


#pragma mark -
#pragma mark CC3MoveTo

CC3MoveTo::CC3MoveTo()
{
}

CC3MoveTo::~CC3MoveTo()
{
}

bool CC3MoveTo::initWithDuration(cocos2d::ccTime t, CC3Vector aLocation)
{
	return CC3TransformBy::initWithDuration(t, aLocation);
}

CC3MoveTo* CC3MoveTo::actionWithDuration(cocos2d::ccTime t, CC3Vector aLocation)
{
	CC3MoveTo* pAction = new CC3MoveTo;
	if (pAction) 
	{
		pAction->autorelease();
		pAction->initWithDuration(t, aLocation);
	}
	
	return pAction;
}

CC3Vector CC3MoveTo::getTargetVector()
{
	return ((CC3Node*)getTarget())->getLocation();
}

void CC3MoveTo::setTargetVector(CC3Vector aVector)
{
	((CC3Node*)getTarget())->setLocation(aVector);
}

//@implementation CC3MoveTo
//
//-(id) initWithDuration: (ccTime) t moveTo: (CC3Vector) aLocation {
//	return [self initWithDuration: t endVector: aLocation];
//}
//
//+(id) actionWithDuration: (ccTime) t moveTo: (CC3Vector) aLocation {
//	return [self actionWithDuration: t endVector: aLocation];
//}
//
//-(CC3Vector) targetVector {
//	return ((CC3Node*)self.target).location;
//}
//
//-(void) setTargetVector: (CC3Vector) aLocation {
//	((CC3Node*)self.target).location = aLocation;
//}
//
//@end


#pragma mark -
#pragma mark CC3RotateTo

CC3RotateTo::CC3RotateTo()
{
}

CC3RotateTo::~CC3RotateTo()
{
}

bool CC3RotateTo::initWithDuration(cocos2d::ccTime t, CC3Vector aRotation)
{
	return CC3TransformTo::initWithDuration(t, aRotation);
}

CC3RotateTo* CC3RotateTo::actionWithDuration(cocos2d::ccTime t, CC3Vector aRotation)
{
	CC3RotateTo* pAction = new CC3RotateTo;
	if (pAction) 
	{
		pAction->autorelease();
		pAction->initWithDuration(t, aRotation);
	}
	
	return pAction;
}

void CC3RotateTo::startWithTarget(cocos2d::CCNode* aTarget)
{
	CC3TransformTo::startWithTarget(aTarget);
	diffVector = CC3VectorRotationalDifference(endVector, startVector);
}

CC3Vector CC3RotateTo::getTargetVector()
{
	return ((CC3Node*)getTarget())->getRotation();
}

void CC3RotateTo::setTargetVector(CC3Vector aVector)
{
	((CC3Node*)getTarget())->setRotation(aVector);
}

//@implementation CC3RotateTo
//
//-(id) initWithDuration: (ccTime) t rotateTo: (CC3Vector) aRotation {
//	return [self initWithDuration: t endVector: aRotation];
//}
//
//+(id) actionWithDuration: (ccTime) t rotateTo: (CC3Vector) aRotation {
//	return [self actionWithDuration: t endVector: aRotation];
//}
//
//// We want to rotate the minimal angles to get from the startVector to the endVector,
//// taking into consideration the cyclical nature of rotation. Therefore, a rotation
//// from 10 degrees to 350 degrees should travel -20 degrees, not the +340 degrees
//// that would result from simple subtraction.
//-(void) startWithTarget:(CC3Node*) aTarget {
//	[super startWithTarget: aTarget];
//	diffVector = CC3VectorRotationalDifference(endVector, startVector);
//}
//
//-(CC3Vector) targetVector {
//	return ((CC3Node*)self.target).rotation;
//}
//
//-(void) setTargetVector: (CC3Vector) aRotation {
//	((CC3Node*)self.target).rotation = aRotation;
//}
//
//@end


#pragma mark -
#pragma mark CC3RotateToAngle

CC3RotateToAngle::CC3RotateToAngle()
{
}

CC3RotateToAngle::~CC3RotateToAngle()
{
}

bool CC3RotateToAngle::initWithDuration(cocos2d::ccTime t, GLfloat anAngle)
{
	if( CC3RotateByAngle::initWithDuration(t, 0) ) 
	{
		endAngle = anAngle;
		return true;
	}
	
	return false;
}

CC3RotateToAngle* CC3RotateToAngle::actionWithDuration(cocos2d::ccTime t, GLfloat anAngle)
{
	CC3RotateToAngle* pAction = new CC3RotateToAngle;
	if (pAction) 
	{
		pAction->autorelease();
		pAction->initWithDuration(t, anAngle);
	}
	
	return pAction;
}

CC3RotateToAngle* CC3RotateToAngle::reverse()
{
	return CC3RotateToAngle::actionWithDuration(getDuration(), diffAngle);
}

void CC3RotateToAngle::startWithTarget(cocos2d::CCNode* aTarget)
{
	CC3RotateByAngle::startWithTarget(aTarget);
	diffAngle = CyclicDifference(endAngle, startAngle, kCircleDegreesPeriod);
}

//@implementation CC3RotateToAngle
//
//-(id) initWithDuration: (ccTime) t rotateToAngle: (GLfloat) anAngle {
//	if( (self = [super initWithDuration: t]) ) {
//		endAngle = anAngle;
//	}
//	return self;
//}
//
//+(id) actionWithDuration: (ccTime) t rotateToAngle: (GLfloat) anAngle {
//	return [[[self alloc] initWithDuration: t rotateToAngle: anAngle] autorelease];
//}
//
//-(id) copyWithZone: (NSZone*) zone {
//	return [[[self class] allocWithZone: zone] initWithDuration: [self duration]
//												  rotateToAngle: endAngle];
//}
//
//-(id) reverse {
//	return [[self class] actionWithDuration: self.duration rotateByAngle: diffAngle];
//}
//
//// We want to rotate the minimal angles to get from the startAngle to the endAngle,
//// taking into consideration the cyclical nature of rotation. Therefore, a rotation
//// from 10 degrees to 350 degrees should travel -20 degrees, not the +340 degrees
//// that would result from simple subtraction.
//-(void) startWithTarget:(CC3Node*) aTarget {
//	[super startWithTarget: aTarget];
//	diffAngle = CyclicDifference(endAngle, startAngle, kCircleDegreesPeriod);
//}
//
//-(NSString*) description {
//	return [NSString stringWithFormat: @"%@ start: %.3f, end: %.3f, diff: %.3f",
//			[self class], startAngle, endAngle, diffAngle];
//}
//
//@end


#pragma mark -
#pragma mark CC3RotateToLookTowards

CC3RotateToLookTowards::CC3RotateToLookTowards()
{
}

CC3RotateToLookTowards::~CC3RotateToLookTowards()
{
}

bool CC3RotateToLookTowards::initWithDuration(cocos2d::ccTime t, CC3Vector aDirection)
{
	return CC3TransformTo::initWithDuration(t, CC3VectorNormalize(aDirection));
}

CC3RotateToLookTowards* CC3RotateToLookTowards::actionWithDuration(cocos2d::ccTime t, CC3Vector aDirection)
{
	CC3RotateToLookTowards* pAction = new CC3RotateToLookTowards;
	if (pAction) 
	{
		pAction->autorelease();
		pAction->initWithDuration(t, aDirection);
	}
	
	return pAction;
}

CC3Vector CC3RotateToLookTowards::getTargetVector()
{
	return ((CC3TargettingNode*)getTarget())->getForwardDirection();
}

void CC3RotateToLookTowards::setTargetVector(CC3Vector aDirection)
{
	((CC3TargettingNode*)getTarget())->setForwardDirection(aDirection);
}

//@implementation CC3RotateToLookTowards
//
//-(id) initWithDuration: (ccTime) t forwardDirection: (CC3Vector) aDirection {
//	return [self initWithDuration: t endVector: CC3VectorNormalize(aDirection)];
//}
//
//+(id) actionWithDuration: (ccTime) t forwardDirection: (CC3Vector) aDirection {
//	return [self actionWithDuration: t endVector: CC3VectorNormalize(aDirection)];
//}
//
//-(CC3Vector) targetVector {
//	return ((CC3TargettingNode*)self.target).forwardDirection;
//}
//
//-(void) setTargetVector: (CC3Vector) aDirection {
//	((CC3TargettingNode*)self.target).forwardDirection = aDirection;
//}
//
//@end


#pragma mark -
#pragma mark CC3RotateToLookAt

CC3RotateToLookAt::CC3RotateToLookAt()
{
}

CC3RotateToLookAt::~CC3RotateToLookAt()
{
}

bool CC3RotateToLookAt::initWithDuration(cocos2d::ccTime t, CC3Vector aLocation)
{
	return CC3RotateToLookTowards::initWithDuration(t, aLocation);
}

CC3RotateToLookAt* CC3RotateToLookAt::actionWithDuration(cocos2d::ccTime t, CC3Vector aLocation)
{
	CC3RotateToLookAt* pAction = new CC3RotateToLookAt;
	if (pAction) 
	{
		pAction->autorelease();
		pAction->initWithDuration(t, aLocation);
	}
	
	return pAction;
}

void CC3RotateToLookAt::startWithTarget(cocos2d::CCNode* aTarget)
{
	endVector = CC3VectorNormalize(CC3VectorDifference(endVector, ((CC3Node*)aTarget)->getGlobalLocation()));
	CC3RotateToLookTowards::startWithTarget(aTarget);
}

//@implementation CC3RotateToLookAt
//
//-(id) initWithDuration: (ccTime) t targetLocation: (CC3Vector) aLocation {
//	return [self initWithDuration: t endVector: aLocation];
//}
//
//+(id) actionWithDuration: (ccTime) t targetLocation: (CC3Vector) aLocation {
//	return [self actionWithDuration: t endVector: aLocation];
//}
//
//-(void) startWithTarget:(CC3Node*) aTarget {
//	endVector = CC3VectorNormalize(CC3VectorDifference(endVector, aTarget.globalLocation));
//	[super startWithTarget: aTarget];
//}
//
//@end


#pragma mark -
#pragma mark CC3ScaleTo

CC3ScaleTo::CC3ScaleTo()
{
}

CC3ScaleTo::~CC3ScaleTo()
{
}

bool CC3ScaleTo::initWithDuration(cocos2d::ccTime t, CC3Vector aScale)
{
	return CC3TransformTo::initWithDuration(t, aScale);
}

CC3ScaleTo* CC3ScaleTo::actionWithDuration(cocos2d::ccTime t, CC3Vector aScale)
{
	CC3ScaleTo* pAction = new CC3ScaleTo;
	if (pAction) 
	{
		pAction->autorelease();
		pAction->initWithDuration(t, aScale);
	}
	
	return pAction;
}

CC3Vector CC3ScaleTo::getTargetVector()
{
	return ((CC3Node*)getTarget())->getScale();
}

void CC3ScaleTo::setTargetVector(CC3Vector aVector)
{
	((CC3Node*)getTarget())->setScale(aVector);
}

//@implementation CC3ScaleTo
//
//-(id) initWithDuration: (ccTime) t scaleTo: (CC3Vector) aScale {
//	return [self initWithDuration: t endVector: aScale];
//}
//
//+(id) actionWithDuration: (ccTime) t scaleTo: (CC3Vector) aScale {
//	return [self actionWithDuration: t endVector: aScale];
//}
//
//-(CC3Vector) targetVector {
//	return ((CC3Node*)self.target).scale;
//}
//
//-(void) setTargetVector: (CC3Vector) aScale {
//	((CC3Node*)self.target).scale = aScale;
//}
//
//@end


#pragma mark -
#pragma mark CC3TintTo

CC3TintTo::CC3TintTo()
{
}

CC3TintTo::~CC3TintTo()
{
}

CC3Node* CC3TintTo::getTargetNode()
{
	return (CC3Node*)getTarget();
}

cocos2d::ccColor4F CC3TintTo::getTargetColor()
{
	return kCCC4FBlackTransparent;
}

void CC3TintTo::setTargetColor(cocos2d::ccColor4F newValue)
{
}

bool CC3TintTo::initWithDuration(cocos2d::ccTime t, cocos2d::ccColor4F aColor)
{
	if( cocos2d::CCActionInterval::initWithDuration(t) ) 
	{
		endColor = aColor;
		return true;
	}
	
	return false;
}

CC3TintTo* CC3TintTo::actionWithDuration(cocos2d::ccTime t, cocos2d::ccColor4F aColor)
{
	CC3TintTo* pAction = new CC3TintTo;
	if (pAction) 
	{
		pAction->autorelease();
		pAction->initWithDuration(t, aColor);
	}
	
	return pAction;
}

void CC3TintTo::startWithTarget(cocos2d::CCNode* aTarget)
{
	cocos2d::CCActionInterval::startWithTarget(aTarget);
	startColor = getTargetColor();
}

void CC3TintTo::update(cocos2d::ccTime t)
{
	setTargetColor(CCC4FBlend(startColor, endColor, t));
}

//@interface CC3TintTo (TemplateMethods)
//@property(nonatomic, assign) ccColor4F targetColor;
//@property(nonatomic, readonly) CC3Node* targetNode;
//@end
//
//@implementation CC3TintTo
//
//-(CC3Node*) targetNode {
//	return (CC3Node*)self.target;
//}
//
//-(ccColor4F) targetColor {
//	NSAssert1(NO, @"%@ is abstract. Property targetColor must be implemented in a concrete subclass", self);
//	return kCCC4FBlackTransparent;
//}
//
//-(void) setTargetColor: (ccColor4F) aColor {
//	NSAssert1(NO, @"%@ is abstract. Property targetColor must be implemented in a concrete subclass", self);
//}
//
//-(id) initWithDuration: (ccTime) t colorTo: (ccColor4F) aColor {
//	if( (self = [super initWithDuration: t]) ) {
//		endColor = aColor;
//	}
//	return self;
//}
//
//+(id) actionWithDuration:(ccTime) t colorTo: (ccColor4F) aColor {
//	return [[[self alloc] initWithDuration: t colorTo: aColor] autorelease];
//}
//
//-(id) copyWithZone: (NSZone*) zone {
//	return [[self class] actionWithDuration: [self duration] colorTo: endColor];
//}
//
//-(void) startWithTarget: (id) aTarget {
//	[super startWithTarget: aTarget];
//	startColor = self.targetColor;
//}
//
//-(void) update: (ccTime) t {
//	self.targetColor = CCC4FBlend(startColor, endColor, t);
//}
//
//@end


#pragma mark -
#pragma mark CC3TintAmbientTo

cocos2d::ccColor4F CC3TintAmbientTo::getTargetColor()
{
	return getTargetNode()->getAmbientColor();
}

void CC3TintAmbientTo::setTargetColor(cocos2d::ccColor4F newValue)
{
	getTargetNode()->setAmbientColor(newValue);
}

//@implementation CC3TintAmbientTo
//
//-(ccColor4F) targetColor {
//	return self.targetNode.ambientColor;
//}
//
//-(void) setTargetColor: (ccColor4F) aColor {
//	self.targetNode.ambientColor = aColor;
//}
//
//@end


#pragma mark -
#pragma mark CC3TintDiffuseTo

cocos2d::ccColor4F CC3TintDiffuseTo::getTargetColor()
{
	return getTargetNode()->getDiffuseColor();
}

void CC3TintDiffuseTo::setTargetColor(cocos2d::ccColor4F newValue)
{
	getTargetNode()->setDiffuseColor(newValue);
}

//@implementation CC3TintDiffuseTo
//
//-(ccColor4F) targetColor {
//	return self.targetNode.diffuseColor;
//}
//
//-(void) setTargetColor: (ccColor4F) aColor {
//	self.targetNode.diffuseColor = aColor;
//}
//
//@end


#pragma mark -
#pragma mark CC3TintSpecularTo

cocos2d::ccColor4F CC3TintSpecularTo::getTargetColor()
{
	return getTargetNode()->getSpecularColor();
}

void CC3TintSpecularTo::setTargetColor(cocos2d::ccColor4F newValue)
{
	getTargetNode()->setSpecularColor(newValue);
}

//@implementation CC3TintSpecularTo
//
//-(ccColor4F) targetColor {
//	return self.targetNode.specularColor;
//}
//
//-(void) setTargetColor: (ccColor4F) aColor {
//	self.targetNode.specularColor = aColor;
//}
//
//@end


#pragma mark -
#pragma mark CC3TintEmissionTo

cocos2d::ccColor4F CC3TintEmissionTo::getTargetColor()
{
	return getTargetNode()->getEmissionColor();
}

void CC3TintEmissionTo::setTargetColor(cocos2d::ccColor4F newValue)
{
	getTargetNode()->setEmissionColor(newValue);
}

//@implementation CC3TintEmissionTo
//
//-(ccColor4F) targetColor {
//	return self.targetNode.emissionColor;
//}
//
//-(void) setTargetColor: (ccColor4F) aColor {
//	self.targetNode.emissionColor = aColor;
//}
//
//@end


#pragma mark -
#pragma mark CC3Animate

CC3Animate::CC3Animate()
{
}

CC3Animate::~CC3Animate()
{
}

bool CC3Animate::getIsReversed()
{
	return isReversed;
}

void CC3Animate::setIsReversed(bool newValue)
{
	isReversed = newValue;
}

cocos2d::CCActionInterval* CC3Animate::asActionLimitedFrom(GLfloat startOfRange, GLfloat endOfRange)
{
	return CC3ActionRangeLimit::actionWithAction(this, startOfRange, endOfRange);
}

cocos2d::CCActionInterval* CC3Animate::actionWithDuration(cocos2d::ccTime d, GLfloat startOfRange, GLfloat endOfRange)
{
	return ((CC3Animate*)actionWithDuration(d))->asActionLimitedFrom(startOfRange, endOfRange);
}

CC3Animate* CC3Animate::actionWithDuration(cocos2d::ccTime t)
{
	CC3Animate* pAnimate = new CC3Animate;
	if (pAnimate) 
	{
		pAnimate->initWithDuration(t);
		pAnimate->autorelease();
	}
	
	return pAnimate;
}

bool CC3Animate::initWithDuration(cocos2d::ccTime d)
{
	if ( CCActionInterval::initWithDuration(d) ) 
	{
		isReversed = false;
		return true;
	}
	
	return false;
}

void CC3Animate::update(cocos2d::ccTime t)
{
	CC3Node* node = (CC3Node*)getTarget();
	node->establishAnimationFrameAt((isReversed ? (1.0 - t) : t));
}

CC3Animate* CC3Animate::reverse()
{
	CC3Animate* newAnim = new CC3Animate;
	if (newAnim) 
	{
		newAnim->autorelease();
		newAnim->initWithDuration(getDuration());
		newAnim->setIsReversed(!getIsReversed());
	}
	
	return newAnim;
}

//@implementation CC3Animate
//
//@synthesize isReversed;
//
//-(id) initWithDuration: (ccTime) d {
//	if ( (self = [super initWithDuration: d]) ) {
//		isReversed = NO;
//	}
//	return self;
//}
//
//-(CCActionInterval*) asActionLimitedFrom: (GLfloat) startOfRange to: (GLfloat) endOfRange {
//	return [CC3ActionRangeLimit actionWithAction: self limitFrom: startOfRange to: endOfRange];
//}
//
//+(id) actionWithDuration: (ccTime) d limitFrom: (GLfloat) startOfRange to: (GLfloat) endOfRange {
//	return [[self actionWithDuration: d] asActionLimitedFrom: startOfRange to: endOfRange];
//}
//
//-(void) update: (ccTime) t {
//	CC3Node* node = target_;
//	[node establishAnimationFrameAt: (isReversed ? (1.0 - t) : t)];
//}
//
//- (CCActionInterval *) reverse {
//	CC3Animate* newAnim = [[self class] actionWithDuration: duration_];
//	newAnim.isReversed = !self.isReversed;
//	return newAnim;
//}
//
//-(id) copyWithZone: (NSZone*) zone {
//	CC3Animate* newAnim = [[[self class] allocWithZone:zone] initWithDuration: duration_];
//	newAnim.isReversed = self.isReversed;
//	return newAnim;
//}
//
//
//@end


#pragma mark -
#pragma mark CC3ActionRangeLimit

CC3ActionRangeLimit::CC3ActionRangeLimit()
{
}

CC3ActionRangeLimit::~CC3ActionRangeLimit()
{
}

bool CC3ActionRangeLimit::initWithAction(CCActionInterval* action, GLfloat startOfRange, GLfloat endOfRange)
{
	if ( CCActionEase::initWithAction(action) ) 
	{
		rangeStart = startOfRange;
		rangeSpan = endOfRange - startOfRange;
		return true;
	}
	
	return false;
}

CC3ActionRangeLimit* CC3ActionRangeLimit::actionWithAction(CCActionInterval* action, GLfloat startOfRange, GLfloat endOfRange)
{
	CC3ActionRangeLimit* pAction = new CC3ActionRangeLimit;
	if (pAction) 
	{
		pAction->initWithAction(action, startOfRange, endOfRange);
		pAction->autorelease();
	}
	
	return pAction;
}

void CC3ActionRangeLimit::update(cocos2d::ccTime t)
{
	m_pOther->update(rangeStart + (rangeSpan * t));
}

CC3ActionRangeLimit* CC3ActionRangeLimit::reverse()
{
	return CC3ActionRangeLimit::actionWithAction(m_pOther, (rangeStart + rangeSpan), rangeStart);
}

//@implementation CC3ActionRangeLimit
//
//-(id) initWithAction: (CCActionInterval*) action
//		   limitFrom: (GLfloat) startOfRange
//				  to: (GLfloat) endOfRange {
//	if ( (self = [super initWithAction: action]) ) {
//		rangeStart = startOfRange;
//		rangeSpan = endOfRange - startOfRange;
//	}
//	return self;
//}
//
//+(id) actionWithAction: (CCActionInterval*) action
//			 limitFrom: (GLfloat) startOfRange
//					to: (GLfloat) endOfRange {
//	return [[[self alloc] initWithAction: action limitFrom: startOfRange to: endOfRange] autorelease];
//}
//
//-(void) update: (ccTime) t {
//	[other update: (rangeStart + (rangeSpan * t))];
//}
//
//- (CCActionInterval *) reverse {
//	return [[self class] actionWithAction: other limitFrom: (rangeStart + rangeSpan) to: rangeStart];
//}
//
//-(id) copyWithZone: (NSZone*) zone {
//	return [[[self class] allocWithZone:zone] initWithAction: other limitFrom: rangeStart to: (rangeStart + rangeSpan)];
//}
//
//@end

